package com.beta.cat.utils;

import java.math.BigDecimal;

/**
 * 高精度计算
 *
 * @author kevin_zhang
 * @date 28/11/2017
 */
public class MathCalcUtil {
    /**
     * 保留精度位数，默认为2位
     */
    private static int scalePub = 2;

    /**
     * 加法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static String add(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return round(b1.add(b2), scalePub);
    }

    /**
     * 减法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static String sub(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return round(b1.subtract(b2), scalePub);
    }

    /**
     * 乘法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static String mul(String v1, String v2) {
        return mul(v1, v2, scalePub);
    }

    /**
     * 乘法
     *
     * @param v1
     * @param v2
     * @param scalePubInput 保留小数位
     * @return
     */
    public static String mul(String v1, String v2, int scalePubInput) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return round(b1.multiply(b2), scalePubInput);
    }

    /**
     * 乘法
     *
     * @param b1
     * @param b2
     * @param scalePubInput 保留小数位
     * @return
     */
    public static String mul(BigDecimal b1, BigDecimal b2, int scalePubInput) {
        return round(b1.multiply(b2), scalePubInput);
    }

    /**
     * 除法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static String div(String v1, String v2) {
        return div(v1, v2, scalePub);
    }

    /**
     * 除法
     *
     * @param v1
     * @param v2
     * @param scale
     * @return
     */
    public static String div(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return (b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)).toString();
    }

    /**
     * 比较大小
     *
     * @param v1
     * @param v2
     * @return -1：v1<v2；0：v1=v2；1：v1>v2
     */
    public static int compareTo(String v1, String v2) {
        return new BigDecimal(v1).compareTo(new BigDecimal(v2));
    }

    /**
     * 对double数字进行精度处理，并将精度后面的数据进行四舍五入
     *
     * @param v
     * @param scale
     * @return
     */
    public static String round(BigDecimal v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal one = new BigDecimal("1");
        return (v.divide(one, scale, BigDecimal.ROUND_HALF_UP)).toString();
    }

    /**
     * 格式化数据-去除后边的0
     *
     * @param v1
     * @return
     */
    public static String formatDecimalStr(String v1) {
        BigDecimal b1 = new BigDecimal(v1);
        return b1.stripTrailingZeros().toPlainString();
    }

    /**
     * 加法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return round(b1.add(b2).doubleValue(), scalePub);
    }

    /**
     * 减法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double sub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return round(b1.subtract(b2).doubleValue(), scalePub);
    }

    /**
     * 乘法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return round(b1.multiply(b2).doubleValue(), scalePub);
    }

    /**
     * 除法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static double div(double v1, double v2) {
        return div(v1, v2, scalePub);
    }

    /**
     * 指定scale参数指定精度位，并将后面的数据四舍五入
     *
     * @param v1
     * @param v2
     * @param scale
     * @return
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");

        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 设置double数字保留精度，并将精度后面的数据进行四舍五入
     *
     * @param v
     * @param scale
     * @return
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");

        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();

    }

    public static void main(String[] args) {
        //System.out.print((0.0==0?0.0:DoubleCalculatorUtil.div(1,0.0)));
    }
}
